home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / MDB / Modules / Manager / mysql.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  39.7 KB  |  960 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP Version 4                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: mysql.php,v 1.44.4.3 2004/01/08 13:43:01 lsmith Exp $
  46. //
  47.  
  48. if(!defined('MDB_MANAGER_MYSQL_INCLUDED'))
  49. {
  50.     define('MDB_MANAGER_MYSQL_INCLUDED', 1);
  51.  
  52. require_once('MDB/Modules/Manager/Common.php');
  53.  
  54. /**
  55.  * MDB MySQL driver for the management modules
  56.  *
  57.  * @package MDB
  58.  * @category Database
  59.  * @access private
  60.  * @author  Lukas Smith <smith@backendmedia.com>
  61.  */
  62. class MDB_Manager_mysql extends MDB_Manager_Common
  63. {
  64.     // {{{ properties
  65.     var $verified_table_types = array();
  66.  
  67.     // }}}
  68.     // {{{ _verifyTransactionalTableType()
  69.  
  70.     /**
  71.      * verify that chosen transactional table hanlder is available in the database
  72.      *
  73.      * @param object    $db        database object that is extended by this class
  74.      * @param string $table_type name of the table handler
  75.      * @return mixed MDB_OK on success, a MDB error on failure
  76.      * @access private
  77.      */
  78.     function _verifyTransactionalTableType(&$db, $table_type)
  79.     {
  80.         switch(strtoupper($table_type)) {
  81.             case 'BERKELEYDB':
  82.             case 'BDB':
  83.                 $check = array('have_bdb');
  84.                 break;
  85.             case 'INNODB':
  86.                 $check = array('have_innobase', 'have_innodb');
  87.                 break;
  88.             case 'GEMINI':
  89.                 $check = array('have_gemini');
  90.                 break;
  91.             case 'HEAP':
  92.             case 'ISAM':
  93.             case 'MERGE':
  94.             case 'MRG_MYISAM':
  95.             case 'MYISAM':
  96.             case '':
  97.                 return(MDB_OK);
  98.             default:
  99.                 return($db->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  100.                     'Verify transactional table',
  101.                     $table_type.' is not a supported table type'));
  102.         }
  103.         if(isset($this->verified_table_types[$table_type])
  104.             && $this->verified_table_types[$table_type] == $db->connection)
  105.         {
  106.             return(MDB_OK);
  107.         }
  108.         $not_supported = false;
  109.         for($i=0, $j=count($check); $i<$j; ++$i) {
  110.             $result = $db->query('SHOW VARIABLES LIKE '.$db->getValue('text', $check[$i]), null, false);
  111.             if (MDB::isError($result)) {
  112.                 return $db->mysqlRaiseError();
  113.             }
  114.             $has = $db->fetchRow($result, MDB_FETCHMODE_ORDERED);
  115.             if (MDB::isError($has)) {
  116.                 return $has;
  117.             }
  118.             if (is_array($has)) {
  119.                 $not_supported = true;
  120.                 if ($has[1] == 'YES') {
  121.                     $this->verified_table_types[$table_type] = $db->connection;
  122.                     return(MDB_OK);
  123.                 }
  124.             }
  125.         }
  126.         if ($not_supported) {
  127.             return($db->raiseError(MDB_ERROR_UNSUPPORTED, null, null,
  128.                 $table_type.' is not a supported table type by this MySQL database server'));
  129.         }
  130.         return($db->raiseError(MDB_ERROR_UNSUPPORTED, null, null,
  131.             'could not tell if '.$table_type.' is a supported table type'));
  132.     }
  133.  
  134.     // }}}
  135.     // {{{ createDatabase()
  136.  
  137.     /**
  138.      * create a new database
  139.      *
  140.      * @param object    $db        database object that is extended by this class
  141.      * @param string $name name of the database that should be created
  142.      * @return mixed MDB_OK on success, a MDB error on failure
  143.      * @access public
  144.      */
  145.     function createDatabase(&$db, $name)
  146.     {
  147.         if (MDB::isError($result = $db->connect())) {
  148.             return($result);
  149.         }
  150.         $query = 'CREATE DATABASE '.$name;
  151.         if(MDB::isError($db->query($query))) {
  152.             return($db->mysqlRaiseError());
  153.         }
  154.  
  155.         return(MDB_OK);
  156.     }
  157.  
  158.     // }}}
  159.     // {{{ dropDatabase()
  160.  
  161.     /**
  162.      * drop an existing database
  163.      *
  164.      * @param object    $db        database object that is extended by this class
  165.      * @param string $name name of the database that should be dropped
  166.      * @return mixed MDB_OK on success, a MDB error on failure
  167.      * @access public
  168.      */
  169.     function dropDatabase(&$db, $name)
  170.     {
  171.         if (MDB::isError($result = $db->connect())) {
  172.             return($result);
  173.         }
  174.         $query = 'DROP DATABASE '.$name;
  175.         if(MDB::isError($db->query($query))) {
  176.             return($db->mysqlRaiseError());
  177.         }
  178.         return(MDB_OK);
  179.     }
  180.  
  181.     // }}}
  182.     // {{{ createTable()
  183.  
  184.     /**
  185.      * create a new table
  186.      *
  187.      * @param object    $db        database object that is extended by this class
  188.      * @param string $name     Name of the database that should be created
  189.      * @param array $fields Associative array that contains the definition of each field of the new table
  190.      *                        The indexes of the array entries are the names of the fields of the table an
  191.      *                        the array entry values are associative arrays like those that are meant to be
  192.      *                         passed with the field definitions to get[Type]Declaration() functions.
  193.      *
  194.      *                        Example
  195.      *                        array(
  196.      *
  197.      *                            'id' => array(
  198.      *                                'type' => 'integer',
  199.      *                                'unsigned' => 1
  200.      *                                'notnull' => 1
  201.      *                                'default' => 0
  202.      *                            ),
  203.      *                            'name' => array(
  204.      *                                'type' => 'text',
  205.      *                                'length' => 12
  206.      *                            ),
  207.      *                            'password' => array(
  208.      *                                'type' => 'text',
  209.      *                                'length' => 12
  210.      *                            )
  211.      *                        );
  212.      * @return mixed MDB_OK on success, a MDB error on failure
  213.      * @access public
  214.      */
  215.     function createTable(&$db, $name, $fields)
  216.     {
  217.         if (!isset($name) || !strcmp($name, '')) {
  218.             return($db->raiseError(MDB_ERROR_CANNOT_CREATE, NULL, NULL, 'no valid table name specified'));
  219.         }
  220.         if (count($fields) == 0) {
  221.             return($db->raiseError(MDB_ERROR_CANNOT_CREATE, NULL, NULL, 'no fields specified for table "'.$name.'"'));
  222.         }
  223.         if(MDB::isError($verify = $this->_verifyTransactionalTableType($db, $db->default_table_type))) {
  224.             return($verify);
  225.         }
  226.         if (MDB::isError($query_fields = $db->getFieldDeclarationList($fields))) {
  227.             return($db->raiseError(MDB_ERROR_CANNOT_CREATE, NULL, NULL, 'unkown error'));
  228.         }
  229.         if (isset($db->supported['Transactions'])
  230.             && $db->default_table_type=='BDB')
  231.         {
  232.             $query_fields .= ', dummy_primary_key INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (dummy_primary_key)';
  233.         }
  234.         $query = "CREATE TABLE $name ($query_fields)".(strlen($db->default_table_type) ? ' TYPE='.$db->default_table_type : '');
  235.  
  236.         return($db->query($query));
  237.     }
  238.  
  239.     // }}}
  240.     // {{{ alterTable()
  241.  
  242.     /**
  243.      * alter an existing table
  244.      *
  245.      * @param object    $db        database object that is extended by this class
  246.      * @param string $name         name of the table that is intended to be changed.
  247.      * @param array $changes     associative array that contains the details of each type
  248.      *                             of change that is intended to be performed. The types of
  249.      *                             changes that are currently supported are defined as follows:
  250.      *
  251.      *                             name
  252.      *
  253.      *                                New name for the table.
  254.      *
  255.      *                            AddedFields
  256.      *
  257.      *                                Associative array with the names of fields to be added as
  258.      *                                 indexes of the array. The value of each entry of the array
  259.      *                                 should be set to another associative array with the properties
  260.      *                                 of the fields to be added. The properties of the fields should
  261.      *                                 be the same as defined by the Metabase parser.
  262.      *
  263.      *                                Additionally, there should be an entry named Declaration that
  264.      *                                 is expected to contain the portion of the field declaration already
  265.      *                                 in DBMS specific SQL code as it is used in the CREATE TABLE statement.
  266.      *
  267.      *                            RemovedFields
  268.      *
  269.      *                                Associative array with the names of fields to be removed as indexes
  270.      *                                 of the array. Currently the values assigned to each entry are ignored.
  271.      *                                 An empty array should be used for future compatibility.
  272.      *
  273.      *                            RenamedFields
  274.      *
  275.      *                                Associative array with the names of fields to be renamed as indexes
  276.      *                                 of the array. The value of each entry of the array should be set to
  277.      *                                 another associative array with the entry named name with the new
  278.      *                                 field name and the entry named Declaration that is expected to contain
  279.      *                                 the portion of the field declaration already in DBMS specific SQL code
  280.      *                                 as it is used in the CREATE TABLE statement.
  281.      *
  282.      *                            ChangedFields
  283.      *
  284.      *                                Associative array with the names of the fields to be changed as indexes
  285.      *                                 of the array. Keep in mind that if it is intended to change either the
  286.      *                                 name of a field and any other properties, the ChangedFields array entries
  287.      *                                 should have the new names of the fields as array indexes.
  288.      *
  289.      *                                The value of each entry of the array should be set to another associative
  290.      *                                 array with the properties of the fields to that are meant to be changed as
  291.      *                                 array entries. These entries should be assigned to the new values of the
  292.      *                                 respective properties. The properties of the fields should be the same
  293.      *                                 as defined by the Metabase parser.
  294.      *
  295.      *                                If the default property is meant to be added, removed or changed, there
  296.      *                                 should also be an entry with index ChangedDefault assigned to 1. Similarly,
  297.      *                                 if the notnull constraint is to be added or removed, there should also be
  298.      *                                 an entry with index ChangedNotNull assigned to 1.
  299.      *
  300.      *                                Additionally, there should be an entry named Declaration that is expected
  301.      *                                 to contain the portion of the field changed declaration already in DBMS
  302.      *                                 specific SQL code as it is used in the CREATE TABLE statement.
  303.      *                            Example
  304.      *                                array(
  305.      *                                    'name' => 'userlist',
  306.      *                                    'AddedFields' => array(
  307.      *                                        'quota' => array(
  308.      *                                            'type' => 'integer',
  309.      *                                            'unsigned' => 1
  310.      *                                            'Declaration' => 'quota INT'
  311.      *                                        )
  312.      *                                    ),
  313.      *                                    'RemovedFields' => array(
  314.      *                                        'file_limit' => array(),
  315.      *                                        'time_limit' => array()
  316.      *                                        ),
  317.      *                                    'ChangedFields' => array(
  318.      *                                        'gender' => array(
  319.      *                                            'default' => 'M',
  320.      *                                            'ChangeDefault' => 1,
  321.      *                                            'Declaration' => "gender CHAR(1) DEFAULT 'M'"
  322.      *                                        )
  323.      *                                    ),
  324.      *                                    'RenamedFields' => array(
  325.      *                                        'sex' => array(
  326.      *                                            'name' => 'gender',
  327.      *                                            'Declaration' => "gender CHAR(1) DEFAULT 'M'"
  328.      *                                        )
  329.      *                                    )
  330.      *                                )
  331.      *
  332.      * @param boolean $check     indicates whether the function should just check if the DBMS driver
  333.      *                             can perform the requested table alterations if the value is true or
  334.      *                             actually perform them otherwise.
  335.      * @access public
  336.      *
  337.       * @return mixed MDB_OK on success, a MDB error on failure
  338.      */
  339.     function alterTable(&$db, $name, $changes, $check)
  340.     {
  341.         if ($check) {
  342.             for($change = 0,reset($changes);
  343.                 $change < count($changes);
  344.                 next($changes), $change++)
  345.             {
  346.                 switch(key($changes)) {
  347.                     case 'AddedFields':
  348.                     case 'RemovedFields':
  349.                     case 'ChangedFields':
  350.                     case 'RenamedFields':
  351.                     case 'name':
  352.                         break;
  353.                     default:
  354.                         return($db->raiseError(MDB_ERROR_CANNOT_ALTER, NULL, NULL,
  355.                             'Alter table: change type "'.Key($changes).'" not yet supported'));
  356.                 }
  357.             }
  358.             return(MDB_OK);
  359.         } else {
  360.             $query = (isset($changes['name']) ? 'RENAME AS '.$changes['name'] : '');
  361.             if (isset($changes['AddedFields'])) {
  362.                 $fields = $changes['AddedFields'];
  363.                 for($field = 0, reset($fields);
  364.                     $field<count($fields);
  365.                     next($fields), $field++)
  366.                 {
  367.                     if (strcmp($query, '')) {
  368.                         $query .= ',';
  369.                     }
  370.                     $query .= 'ADD '.$fields[key($fields)]['Declaration'];
  371.                 }
  372.             }
  373.             if (isset($changes['RemovedFields'])) {
  374.                 $fields = $changes['RemovedFields'];
  375.                 for($field = 0,reset($fields);
  376.                     $field<count($fields);
  377.                     next($fields), $field++)
  378.                 {
  379.                     if (strcmp($query, '')) {
  380.                         $query .= ',';
  381.                     }
  382.                     $query .= 'DROP '.key($fields);
  383.                 }
  384.             }
  385.             $renamed_fields = array();
  386.             if (isset($changes['RenamedFields'])) {
  387.                 $fields = $changes['RenamedFields'];
  388.                 for($field = 0,reset($fields);
  389.                     $field<count($fields);
  390.                     next($fields), $field++)
  391.                 {
  392.                     $renamed_fields[$fields[key($fields)]['name']] = key($fields);
  393.                 }
  394.             }
  395.             if (isset($changes['ChangedFields'])) {
  396.                 $fields = $changes['ChangedFields'];
  397.                 for($field = 0,reset($fields);
  398.                     $field<count($fields);
  399.                     next($fields), $field++)
  400.                 {
  401.                     if (strcmp($query, '')) {
  402.                         $query .= ',';
  403.                     }
  404.                     if (isset($renamed_fields[key($fields)])) {
  405.                         $field_name = $renamed_fields[key($fields)];
  406.                         unset($renamed_fields[key($fields)]);
  407.                     } else {
  408.                         $field_name = key($fields);
  409.                     }
  410.                     $query .= "CHANGE $field_name ".$fields[key($fields)]['Declaration'];
  411.                 }
  412.             }
  413.             if (count($renamed_fields))
  414.             {
  415.                 for($field = 0,reset($renamed_fields);
  416.                     $field<count($renamed_fields);
  417.                     next($renamed_fields), $field++)
  418.                 {
  419.                     if (strcmp($query, '')) {
  420.                         $query .= ',';
  421.                     }
  422.                     $old_field_name = $renamed_fields[Key($renamed_fields)];
  423.                     $query .= "CHANGE $old_field_name ".$changes['RenamedFields'][$old_field_name]['Declaration'];
  424.                 }
  425.             }
  426.             return($db->query("ALTER TABLE $name $query"));
  427.         }
  428.     }
  429.  
  430.     // }}}
  431.     // {{{ listDatabases()
  432.  
  433.     /**
  434.      * list all databases
  435.      *
  436.      * @param object    $db        database object that is extended by this class
  437.      * @return mixed data array on success, a MDB error on failure
  438.      * @access public
  439.      */
  440.     function listDatabases(&$db)
  441.     {
  442.         $result = $db->queryCol('SHOW DATABASES');
  443.         if(MDB::isError($result)) {
  444.             return($result);
  445.         }
  446.         return($result);
  447.     }
  448.  
  449.     // }}}
  450.     // {{{ listUsers()
  451.  
  452.     /**
  453.      * list all users
  454.      *
  455.      * @param object    $db        database object that is extended by this class
  456.      * @return mixed data array on success, a MDB error on failure
  457.      * @access public
  458.      */
  459.     function listUsers(&$db)
  460.     {
  461.         $result = $db->queryCol('SELECT DISTINCT USER FROM USER');
  462.         if(MDB::isError($result)) {
  463.             return($result);
  464.         }
  465.         return($result);
  466.     }
  467.  
  468.     // }}}
  469.     // {{{ listTables()
  470.  
  471.     /**
  472.      * list all tables in the current database
  473.      *
  474.      * @param object    $db        database object that is extended by this class
  475.      * @return mixed data array on success, a MDB error on failure
  476.      * @access public
  477.      */
  478.     function listTables(&$db)
  479.     {
  480.         $table_names = $db->queryCol('SHOW TABLES');
  481.         if(MDB::isError($table_names)) {
  482.             return($table_names);
  483.         }
  484.         for($i = 0, $j = count($table_names), $tables = array(); $i < $j; ++$i)
  485.         {
  486.             if (!$this->_isSequenceName($db, $table_names[$i]))
  487.                 $tables[] = $table_names[$i];
  488.         }
  489.         return($tables);
  490.     }
  491.  
  492.     // }}}
  493.     // {{{ listTableFields()
  494.  
  495.     /**
  496.      * list all fields in a tables in the current database
  497.      *
  498.      * @param object    $db        database object that is extended by this class
  499.      * @param string $table name of table that should be used in method
  500.      * @return mixed data array on success, a MDB error on failure
  501.      * @access public
  502.      */
  503.     function listTableFields(&$db, $table)
  504.     {
  505.         $result = $db->query("SHOW COLUMNS FROM $table");
  506.         if(MDB::isError($result)) {
  507.             return($result);
  508.         }
  509.         $columns = $db->getColumnNames($result);
  510.         if(MDB::isError($columns)) {
  511.             $db->freeResult($columns);
  512.             return($columns);
  513.         }
  514.         if(!isset($columns['field'])) {
  515.             $db->freeResult($result);
  516.             return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
  517.                 'List table fields: show columns does not return the table field names'));
  518.         }
  519.         $field_column = $columns['field'];
  520.         for($fields = array(), $field = 0; !$db->endOfResult($result); ++$field) {
  521.             $field_name = $db->fetch($result, $field, $field_column);
  522.             if ($field_name != $db->dummy_primary_key)
  523.                 $fields[] = $field_name;
  524.         }
  525.         $db->freeResult($result);
  526.         return($fields);
  527.     }
  528.  
  529.     // }}}
  530.     // {{{ getTableFieldDefinition()
  531.  
  532.     /**
  533.      * get the stucture of a field into an array
  534.      *
  535.      * @param object    $db        database object that is extended by this class
  536.      * @param string    $table         name of table that should be used in method
  537.      * @param string    $field_name     name of field that should be used in method
  538.      * @return mixed data array on success, a MDB error on failure
  539.      * @access public
  540.      */
  541.     function getTableFieldDefinition(&$db, $table, $field_name)
  542.     {
  543.         if ($field_name == $db->dummy_primary_key) {
  544.             return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
  545.                 'Get table field definiton: '.$db->dummy_primary_key.' is an hidden column'));
  546.         }
  547.         $result = $db->query("SHOW COLUMNS FROM $table");
  548.         if(MDB::isError($result)) {
  549.             return($result);
  550.         }
  551.         $columns = $db->getColumnNames($result);
  552.         if(MDB::isError($columns)) {
  553.             $db->freeResult($columns);
  554.             return($columns);
  555.         }
  556.         if (!isset($columns[$column = 'field'])
  557.             || !isset($columns[$column = 'type']))
  558.         {
  559.             $db->freeResult($result);
  560.             return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
  561.                 'Get table field definition: show columns does not return the column '.$column));
  562.         }
  563.         $field_column = $columns['field'];
  564.         $type_column = $columns['type'];
  565.         while (is_array($row = $db->fetchInto($result))) {
  566.             if ($field_name == $row[$field_column]) {
  567.                 $db_type = strtolower($row[$type_column]);
  568.                 $db_type = strtok($db_type, '(), ');
  569.                 if ($db_type == 'national') {
  570.                     $db_type = strtok('(), ');
  571.                 }
  572.                 $length = strtok('(), ');
  573.                 $decimal = strtok('(), ');
  574.                 $type = array();
  575.                 switch($db_type) {
  576.                     case 'tinyint':
  577.                     case 'smallint':
  578.                     case 'mediumint':
  579.                     case 'int':
  580.                     case 'integer':
  581.                     case 'bigint':
  582.                         $type[0] = 'integer';
  583.                         if($length == '1') {
  584.                             $type[1] = 'boolean';
  585.                             if (preg_match('/^[is|has]/', $field_name)) {
  586.                                 $type = array_reverse($type);
  587.                             }
  588.                         }
  589.                         break;
  590.                     case 'tinytext':
  591.                     case 'mediumtext':
  592.                     case 'longtext':
  593.                     case 'text':
  594.                     case 'char':
  595.                     case 'varchar':
  596.                         $type[0] = 'text';
  597.                         if($decimal == 'binary') {
  598.                             $type[1] = 'blob';
  599.                         } elseif($length == '1') {
  600.                             $type[1] = 'boolean';
  601.                             if (preg_match('/[is|has]/', $field_name)) {
  602.                                 $type = array_reverse($type);
  603.                             }
  604.                         } elseif(strstr($db_type, 'text'))
  605.                             $type[1] = 'clob';
  606.                         break;
  607.                     case 'enum':
  608.                         preg_match_all('/\'.+\'/U',$row[$type_column], $matches);
  609.                         $length = 0;
  610.                         if(is_array($matches)) {
  611.                             foreach($matches[0] as $value) {
  612.                                 $length = max($length, strlen($value)-2);
  613.                             }
  614.                         }
  615.                         unset($decimal);
  616.                     case 'set':
  617.                         $type[0] = 'text';
  618.                         $type[1] = 'integer';
  619.                         break;
  620.                     case 'date':
  621.                         $type[0] = 'date';
  622.                         break;
  623.                     case 'datetime':
  624.                     case 'timestamp':
  625.                         $type[0] = 'timestamp';
  626.                         break;
  627.                     case 'time':
  628.                         $type[0] = 'time';
  629.                         break;
  630.                     case 'float':
  631.                     case 'double':
  632.                     case 'real':
  633.                         $type[0] = 'float';
  634.                         break;
  635.                     case 'decimal':
  636.                     case 'numeric':
  637.                         $type[0] = 'decimal';
  638.                         break;
  639.                     case 'tinyblob':
  640.                     case 'mediumblob':
  641.                     case 'longblob':
  642.                     case 'blob':
  643.                         $type[0] = 'blob';
  644.                         $type[1] = 'text';
  645.                         break;
  646.                     case 'year':
  647.                         $type[0] = 'integer';
  648.                         $type[1] = 'date';
  649.                         break;
  650.                     default:
  651.                         return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
  652.                             'List table fields: unknown database attribute type'));
  653.                 }
  654.                 unset($notnull);
  655.                 if (isset($columns['null'])
  656.                     && $row[$columns['null']] != 'YES')
  657.                 {
  658.                     $notnull = 1;
  659.                 }
  660.                 unset($default);
  661.                 if (isset($columns['default'])
  662.                     && isset($row[$columns['default']]))
  663.                 {
  664.                     $default = $row[$columns['default']];
  665.                 }
  666.                 $definition = array();
  667.                 for($field_choices = array(), $datatype = 0; $datatype < count($type); $datatype++) {
  668.                     $field_choices[$datatype] = array('type' => $type[$datatype]);
  669.                     if(isset($notnull)) {
  670.                         $field_choices[$datatype]['notnull'] = 1;
  671.                     }
  672.                     if(isset($default)) {
  673.                         $field_choices[$datatype]['default'] = $default;
  674.                     }
  675.                     if($type[$datatype] != 'boolean'
  676.                         && $type[$datatype] != 'time'
  677.                         && $type[$datatype] != 'date'
  678.                         && $type[$datatype] != 'timestamp')
  679.                     {
  680.                         if(strlen($length)) {
  681.                             $field_choices[$datatype]['length'] = $length;
  682.                         }
  683.                     }
  684.                 }
  685.                 $definition[0] = $field_choices;
  686.                 if (isset($columns['extra'])
  687.                     && isset($row[$columns['extra']])
  688.                     && $row[$columns['extra']] == 'auto_increment')
  689.                 {
  690.                     $implicit_sequence = array();
  691.                     $implicit_sequence['on'] = array();
  692.                     $implicit_sequence['on']['table'] = $table;
  693.                     $implicit_sequence['on']['field'] = $field_name;
  694.                     $definition[1]['name'] = $table.'_'.$field_name;
  695.                     $definition[1]['definition'] = $implicit_sequence;
  696.                 }
  697.                 if (isset($columns['key'])
  698.                     && isset($row[$columns['key']])
  699.                     && $row[$columns['key']] == 'PRI')
  700.                 {
  701.                     // check that its not just a unique field
  702.                     if(MDB::isError($indexes = $db->queryAll("SHOW INDEX FROM $table", NULL, MDB_FETCHMODE_ASSOC))) {
  703.                         return($indexes);
  704.                     }
  705.                     $is_primary = FALSE;
  706.                     foreach($indexes as $index) {
  707.                         if ($index['Key_name'] == 'PRIMARY' && $index['Column_name'] == $field_name) {
  708.                             $is_primary = TRUE;
  709.                             break;
  710.                         }
  711.                     }
  712.                     if($is_primary) {
  713.                         $implicit_index = array();
  714.                         $implicit_index['unique'] = 1;
  715.                         $implicit_index['FIELDS'][$field_name] = '';
  716.                         $definition[2]['name'] = $field_name;
  717.                         $definition[2]['definition'] = $implicit_index;
  718.                     }
  719.                 }
  720.                 $db->freeResult($result);
  721.                 return($definition);
  722.             }
  723.         }
  724.         if(!$db->options['autofree']) {
  725.             $db->freeResult($result);
  726.         }
  727.         if(MDB::isError($row)) {
  728.             return($row);
  729.         }
  730.         return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL,
  731.             'Get table field definition: it was not specified an existing table column'));
  732.     }
  733.  
  734.     // }}}
  735.     // {{{ createIndex()
  736.  
  737.     /**
  738.      * get the stucture of a field into an array
  739.      *
  740.      * @param object    $db        database object that is extended by this class
  741.      * @param string    $table         name of the table on which the index is to be created
  742.      * @param string    $name         name of the index to be created
  743.      * @param array     $definition        associative array that defines properties of the index to be created.
  744.      *                                 Currently, only one property named FIELDS is supported. This property
  745.      *                                 is also an associative with the names of the index fields as array
  746.      *                                 indexes. Each entry of this array is set to another type of associative
  747.      *                                 array that specifies properties of the index that are specific to
  748.      *                                 each field.
  749.      *
  750.      *                                Currently, only the sorting property is supported. It should be used
  751.      *                                 to define the sorting direction of the index. It may be set to either
  752.      *                                 ascending or descending.
  753.      *
  754.      *                                Not all DBMS support index sorting direction configuration. The DBMS
  755.      *                                 drivers of those that do not support it ignore this property. Use the
  756.      *                                 function support() to determine whether the DBMS driver can manage indexes.
  757.  
  758.      *                                 Example
  759.      *                                    array(
  760.      *                                        'FIELDS' => array(
  761.      *                                            'user_name' => array(
  762.      *                                                'sorting' => 'ascending'
  763.      *                                            ),
  764.      *                                            'last_login' => array()
  765.      *                                        )
  766.      *                                    )
  767.      * @return mixed MDB_OK on success, a MDB error on failure
  768.      * @access public
  769.      */
  770.     function createIndex(&$db, $table, $name, $definition)
  771.     {
  772.         $query = "ALTER TABLE $table ADD ".(isset($definition['unique']) ? 'UNIQUE' : 'INDEX')." $name (";
  773.         for($field = 0, reset($definition['FIELDS']);
  774.             $field < count($definition['FIELDS']);
  775.             $field++, next($definition['FIELDS']))
  776.         {
  777.             if ($field > 0) {
  778.                 $query .= ',';
  779.             }
  780.             $query .= key($definition['FIELDS']);
  781.         }
  782.         $query .= ')';
  783.         return($db->query($query));
  784.     }
  785.  
  786.     // }}}
  787.     // {{{ dropIndex()
  788.  
  789.     /**
  790.      * drop existing index
  791.      *
  792.      * @param object    $db        database object that is extended by this class
  793.      * @param string    $table         name of table that should be used in method
  794.      * @param string    $name         name of the index to be dropped
  795.      * @return mixed MDB_OK on success, a MDB error on failure
  796.      * @access public
  797.      */
  798.     function dropIndex(&$db, $table, $name)
  799.     {
  800.         return($db->query("ALTER TABLE $table DROP INDEX $name"));
  801.     }
  802.  
  803.     // }}}
  804.     // {{{ listTableIndexes()
  805.  
  806.     /**
  807.      * list all indexes in a table
  808.      *
  809.      * @param object    $db        database object that is extended by this class
  810.      * @param string    $table      name of table that should be used in method
  811.      * @return mixed data array on success, a MDB error on failure
  812.      * @access public
  813.      */
  814.     function listTableIndexes(&$db, $table)
  815.     {
  816.         if(MDB::isError($result = $db->query("SHOW INDEX FROM $table"))) {
  817.             return($result);
  818.         }
  819.         $indexes_all = $db->fetchCol($result, 'Key_name');
  820.         for($found = $indexes = array(), $index = 0, $indexes_all_cnt = count($indexes_all);
  821.             $index < $indexes_all_cnt;
  822.             $index++)
  823.         {
  824.             if ($indexes_all[$index] != 'PRIMARY'
  825.                 && !isset($found[$indexes_all[$index]]))
  826.             {
  827.                 $indexes[] = $indexes_all[$index];
  828.                 $found[$indexes_all[$index]] = 1;
  829.             }
  830.         }
  831.         return($indexes);
  832.     }
  833.  
  834.     // }}}
  835.     // {{{ getTableIndexDefinition()
  836.  
  837.     /**
  838.      * get the stucture of an index into an array
  839.      *
  840.      * @param object    $db        database object that is extended by this class
  841.      * @param string    $table      name of table that should be used in method
  842.      * @param string    $index_name name of index that should be used in method
  843.      * @return mixed data array on success, a MDB error on failure
  844.      * @access public
  845.      */
  846.     function getTableIndexDefinition(&$db, $table, $index_name)
  847.     {
  848.         if($index_name == 'PRIMARY') {
  849.             return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL, 'Get table index definition: PRIMARY is an hidden index'));
  850.         }
  851.         if(MDB::isError($result = $db->query("SHOW INDEX FROM $table"))) {
  852.             return($result);
  853.         }
  854.         $definition = array();
  855.         while (is_array($row = $db->fetchInto($result, MDB_FETCHMODE_ASSOC))) {
  856.             $key_name = $row['Key_name'];
  857.             if(!strcmp($index_name, $key_name)) {
  858.                 if(!$row['Non_unique']) {
  859.                     $definition[$index_name]['unique'] = 1;
  860.                 }
  861.                 $column_name = $row['Column_name'];
  862.                 $definition['FIELDS'][$column_name] = array();
  863.                 if(isset($row['Collation'])) {
  864.                     $definition['FIELDS'][$column_name]['sorting'] = ($row['Collation'] == 'A' ? 'ascending' : 'descending');
  865.                 }
  866.             }
  867.         }
  868.         $db->freeResult($result);
  869.         if (!isset($definition['FIELDS'])) {
  870.             return($db->raiseError(MDB_ERROR_MANAGER, NULL, NULL, 'Get table index definition: it was not specified an existing table index'));
  871.         }
  872.         return($definition);
  873.     }
  874.  
  875.     // }}}
  876.     // {{{ createSequence()
  877.  
  878.     /**
  879.      * create sequence
  880.      *
  881.      * @param object    $db        database object that is extended by this class
  882.      * @param string    $seq_name     name of the sequence to be created
  883.      * @param string    $start         start value of the sequence; default is 1
  884.      * @return mixed MDB_OK on success, a MDB error on failure
  885.      * @access public
  886.      */
  887.     function createSequence(&$db, $seq_name, $start)
  888.     {
  889.         $sequence_name = $db->getSequenceName($seq_name);
  890.         $res = $db->query("CREATE TABLE $sequence_name
  891.             (sequence INT DEFAULT 0 NOT NULL AUTO_INCREMENT, PRIMARY KEY (sequence))");
  892.         if (MDB::isError($res)) {
  893.             return($res);
  894.         }
  895.         if ($start == 1) {
  896.             return(MDB_OK);
  897.         }
  898.         $res = $db->query("INSERT INTO $sequence_name (sequence) VALUES (".($start-1).')');
  899.         if (!MDB::isError($res)) {
  900.             return(MDB_OK);
  901.         }
  902.         // Handle error
  903.         $result = $db->query("DROP TABLE $sequence_name");
  904.         if (MDB::isError($result)) {
  905.             return($db->raiseError(MDB_ERROR, NULL, NULL,
  906.                 'Create sequence: could not drop inconsistent sequence table ('.
  907.                 $result->getMessage().' ('.$result->getUserinfo().'))'));
  908.         }
  909.         return($db->raiseError(MDB_ERROR, NULL, NULL,
  910.             'Create sequence: could not create sequence table ('.
  911.             $res->getMessage().' ('.$res->getUserinfo().'))'));
  912.     }
  913.  
  914.     // }}}
  915.     // {{{ dropSequence()
  916.  
  917.     /**
  918.      * drop existing sequence
  919.      *
  920.      * @param object    $db        database object that is extended by this class
  921.      * @param string    $seq_name     name of the sequence to be dropped
  922.      * @return mixed MDB_OK on success, a MDB error on failure
  923.      * @access public
  924.      */
  925.     function dropSequence(&$db, $seq_name)
  926.     {
  927.         $sequence_name = $db->getSequenceName($seq_name);
  928.         return($db->query("DROP TABLE $sequence_name"));
  929.     }
  930.  
  931.     // }}}
  932.     // {{{ listSequences()
  933.  
  934.     /**
  935.      * list all sequences in the current database
  936.      *
  937.      * @param object    $db        database object that is extended by this class
  938.      * @return mixed data array on success, a MDB error on failure
  939.      * @access public
  940.      */
  941.     function listSequences(&$db)
  942.     {
  943.         $table_names = $db->queryCol('SHOW TABLES');
  944.         if(MDB::isError($table_names)) {
  945.             return($table_names);
  946.         }
  947.         for($i = 0, $j = count($table_names), $sequences = array(); $i < $j; ++$i)
  948.         {
  949.             if ($sqn = $this->_isSequenceName($db, $table_names[$i]))
  950.                 $sequences[] = $sqn;
  951.         }
  952.         return($sequences);
  953.     }
  954.  
  955.     // }}}
  956. }
  957.  
  958. };
  959. ?>
  960.